package data_structure.mooc;

/**
 * An array of secondary packing
 * Is the Generic Class
 * Complete addition,deletion,modification,look-up operation of an array
 * Can resize the capacity with the size changing:
 * If the size is less than a quarter of the capacity,the capacity will become a half of original
 * Once the size greater than the capacity,the capacity will become twice as long
 * The default capacity is 10
 */
public class Array<E>{

    private E []array;
    private int size;

    /**
     * constructor with argument capacity
     * @param capacity int
     */
    public Array(int capacity){
        this.array = (E[])new Object[capacity];
        size=0;
    }

    public Array(E []array){

        this.array=(E[])new Object[array.length];
        for(int i = 0; i < array.length; i++){
            this.array[i] = array[i];
        }
        size=array.length;
    }

    public Array(){
        this(10);
    }

    public boolean isEmpty(){
        return this.size == 0;
    }

    /**
     *
     * @return int the size of this array
     */
    public int  getSize(){
        return this.size;
    }

    /**
     *
     * @return int the capacity of this array
     */
    public int getCapacity(){
        return array.length;
    }

    public void addLast(E e){
        add (e,size);
    }

    public void addFirst(E e){
        add (e,0);
    }

    /**
     * Add the element to the special position in the array
     * Can resize based on the size relationship between size and capacity
     * @param e E
     * @param index int
     */
    public void add(E e,int index){
        //检查容量，是否扩容
        if(size==array.length){
           reSize (array.length*2);
        }
        //处理不合法的index
        if(index<0||index>=array.length){
            throw new IllegalArgumentException("add failed,the index of element must greater than 0 and less than the capacity of array");
        }
        //index后面的元素，包括index在内全部向后移动一位，相当于把前面的值赋给后面的变量
        for(int i=size-1;i>=index;i--){
            array[i+1]=array[i];
        }
        array[index]=e;
        size++;
    }


    public void swap(int i,int j){

        if(i<0||j<0||i>=array.length||j>=array.length){
            throw new IllegalArgumentException("index is invalid");
        }
        E temp=array[i];
        array[i]=array[j];
        array[j] = temp;
    }

    @Override
    public String toString() {

        StringBuilder sb = new StringBuilder();
        sb.append (String.format("Array size=%d capacity=%d ",size,array.length));
        sb.append("[");
        for(int i=0;i<size;i++){
            sb.append(array[i]);
            if(i!=size-1){
                sb.append(",");
            }
        }
        sb.append("]");
        return sb.toString ();
    }
    public E get(int index){
        if(index < 0 || index >= size){
            throw new IllegalArgumentException ("get failed ,get illegal");
        }
        return array[index];
    }

    public void set(E e,int index){
        if(index < 0 || index >= size){
            throw new IllegalArgumentException ("set failed ,set illegal");
        }
        array[index] = e;
    }

    public int find(E e){

        for(int i = 0; i <size; i++){
            if (array[i].equals (e)) {
                return i;
            }
        }
        return -1;
    }

    /**
     * Delete the element of special position in this array
     * @param index int
     * @return E the deleted element
     */
    public E remove (int index){

        if (index < 0 || index >= size) {
            throw new IllegalArgumentException("remove failed,index is illegal");
        }
        E temp=array[index];
        for(int i=index+1;i<size;i++){
            array[i-1]=array[i];
        }

        size--;
        if(size==array.length/4&&array.length/2!=0){
            reSize (array.length / 2);
        }
        return temp;
    }
    public E removeFirst(){
        return remove (0);
    }
    public E removeLast() {
        return remove (size - 1);
    }

    public void removeElement(E e){
        int flag=find (e);
        if(flag==-1){
            throw new IllegalArgumentException("remove failed,the element is not found");
        }
        else{
            remove (flag);
        }
    }

    /**
     * Resize the capacity
     * @param newCapacity int new capacity of this array
     */
    private void reSize(int newCapacity){
        E[] newArray = (E[])new Object[newCapacity];
        for(int i = 0; i < size; i++){
            newArray[i]=array[i];
        }
        array=newArray;
    }
    public E getLast(){
        return get(size-1);
    }
    public E getFirst(){
        return get(0);
    }


    public static void main(String[] args) {
        Array<Integer> array = new Array<>(6);
        for(int i = 0; i <6;i++){
            array.addLast (i);
        }
//        array.add (2,8);
//        array.addFirst (-1);
//        System.out.println(array.toString ());
//        System.out.println(array.get (4));
//        array.set (100,4);
//        System.out.println(array.toString ());
        array.addLast(10);
        array.addLast(100);
        System.out.println(array.toString ());
        array.removeFirst ();
        array.removeFirst ();
        array.removeFirst ();
        System.out.println(array.toString());
    }


}
